package management;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 学生成绩管理系统核心类，包含所有业务逻辑和文件存储
 */
public class ScoreManagementSystem {
    private List<Student> students = new ArrayList<>();
    private List<Course> courses = new ArrayList<>();
    private List<Score> scores = new ArrayList<>();

    /**
     * 添加学生（校验学号唯一性）
     */
    public void addStudent(Student student) {
        if (students.contains(student)) {
            System.out.println("学生已存在（学号：" + student.getStudentId() + "）");
            return;
        }
        students.add(student);
        System.out.println("添加学生成功：" + student);
    }

    /**
     * 添加课程（校验课程编号唯一性）
     */
    public void addCourse(Course course) {
        for (Course c : courses) {
            if (c.getCourseId().equals(course.getCourseId())) {
                System.out.println("课程已存在（编号：" + course.getCourseId() + "，学分：" + course.getCredit() + "）");
                return;
            }
        }
        courses.add(course);
        System.out.println("添加课程成功：" + course);
    }

    /**
     * 添加成绩（关联学生和课程，处理分数异常）
     */
    public void addScore(String studentId, String courseId, double score) {
        Student student = findStudentById(studentId);
        if (student == null) {
            System.out.println("学生不存在（学号：" + studentId + "）");
            return;
        }

        Course course = findCourseById(courseId);
        if (course == null) {
            System.out.println("课程不存在（编号：" + courseId + "）");
            return;
        }

        if (hasDuplicateScore(studentId, courseId)) {
            System.out.println("成绩已存在：" + student.getName() + " - " + course.getName() + "（学分：" + course.getCredit() + "）");
            return;
        }

        try {
            scores.add(new Score(student, course, score));
            System.out.println("添加成绩成功：" + student.getName() + " - " + course.getName() + "（学分：" + course.getCredit() + "）");
        } catch (InvalidScoreException e) {
            System.out.println("添加成绩失败：" + e.getMessage());
        }
    }

    /**
     * 查询某课程的所有成绩（含学分）
     */
    public List<Score> queryScoresByCourse(String courseName) {
        List<Score> result = new ArrayList<>();
        System.out.println("\n===== 课程《" + courseName + "》成绩查询结果（含学分）=====");
        for (Score score : scores) {
            if (score.getCourse().getName().equals(courseName)) {
                result.add(score);
                System.out.println(score);
            }
        }
        if (result.isEmpty()) {
            System.out.println("该课程无成绩记录");
        }
        return result;
    }

    /**
     * 计算学生GPA（显示学分统计）
     */
    public double calculateGPA(String studentId) {
        Student student = findStudentById(studentId);
        if (student == null) {
            System.out.println("学生不存在（学号：" + studentId + "）");
            return 0.0;
        }

        double totalPoints = 0.0;
        int totalCredits = 0;      // 及格课程总学分
        int allCourseCredits = 0;  // 所有课程总学分

        for (Score score : scores) {
            if (score.getStudent().getStudentId().equals(studentId)) {
                int credit = score.getCourse().getCredit();
                allCourseCredits += credit;
                if (score.getScore() >= 60) {
                    totalPoints += (score.getScore() / 20) * credit;
                    totalCredits += credit;
                }
            }
        }

        double gpa = totalCredits == 0 ? 0.0 : Math.round((totalPoints / totalCredits) * 100) / 100.0;
        System.out.println(student.getName() + "（学号：" + studentId + "）的GPA信息：");
        System.out.println("  所有课程总学分：" + allCourseCredits);
        System.out.println("  及格课程总学分：" + totalCredits);
        System.out.println("  GPA：" + gpa);
        return gpa;
    }

    /**
     * 保存数据到CSV（含学生GPA数据）
     */
    public void saveData() {
        String csvFile = "score_management.csv";

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvFile))) {
            // 1. 学生数据
            writer.write("学生数据：学号,姓名,班级");
            writer.newLine();
            for (Student s : students) {
                writer.write(s.getStudentId() + "," + s.getName() + "," + s.getClassName());
                writer.newLine();
            }

            // 2. 课程数据
            writer.newLine();
            writer.write("课程数据：课程编号,课程名称,学分");
            writer.newLine();
            for (Course c : courses) {
                writer.write(c.getCourseId() + "," + c.getName() + "," + c.getCredit());
                writer.newLine();
            }

            // 3. 成绩数据
            writer.newLine();
            writer.write("成绩数据：学号,姓名,班级,课程编号,课程名称,分数,学分");
            writer.newLine();
            for (Score sc : scores) {
                writer.write(
                    sc.getStudent().getStudentId() + "," +
                    sc.getStudent().getName() + "," +
                    sc.getStudent().getClassName() + "," +
                    sc.getCourse().getCourseId() + "," +
                    sc.getCourse().getName() + "," +
                    sc.getScore() + "," +
                    sc.getCourse().getCredit()
                );
                writer.newLine();
            }

            // 4. 学生GPA数据（新增）
            writer.newLine();
            writer.write("学生GPA数据：学号,姓名,班级,所有课程总学分,及格课程总学分,GPA");
            writer.newLine();
            for (Student s : students) {
                String studentId = s.getStudentId();
                double gpa = calculateGPAForSave(studentId);
                int[] credits = getCreditStats(studentId);
                writer.write(
                    studentId + "," +
                    s.getName() + "," +
                    s.getClassName() + "," +
                    credits[0] + "," +  // 所有课程总学分
                    credits[1] + "," +  // 及格课程总学分
                    gpa
                );
                writer.newLine();
            }

            System.out.println("\n数据已保存到CSV文件（含GPA信息）：" + csvFile);
        } catch (IOException e) {
            System.out.println("保存失败：" + e.getMessage());
        }
    }

    /**
     * 从CSV加载数据
     */
    public void loadData() {
        String csvFile = "score_management.csv";
        File file = new File(csvFile);
        if (!file.exists()) {
            System.out.println("无历史数据，将创建新系统");
            return;
        }

        try (BufferedReader reader = new BufferedReader(new FileReader(csvFile))) {
            String line;
            int dataType = 0; // 1：学生，2：课程，3：成绩，4：GPA（仅加载前3类用于系统运行）

            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.isEmpty()) continue;

                // 识别数据类型
                if (line.startsWith("学生数据：")) {
                    dataType = 1;
                    continue;
                } else if (line.startsWith("课程数据：")) {
                    dataType = 2;
                    continue;
                } else if (line.startsWith("成绩数据：")) {
                    dataType = 3;
                    continue;
                } else if (line.startsWith("学生GPA数据：")) {
                    dataType = 4; // GPA数据仅用于存储，不加载到系统（系统运行时实时计算）
                    continue;
                }

                String[] parts = line.split(",");
                switch (dataType) {
                    case 1: // 学生数据
                        if (parts.length == 3) {
                            addStudent(new Student(parts[0], parts[1], parts[2]));
                        }
                        break;
                    case 2: // 课程数据
                        if (parts.length == 3) {
                            addCourse(new Course(parts[0], parts[1], Integer.parseInt(parts[2])));
                        }
                        break;
                    case 3: // 成绩数据
                        if (parts.length == 7) {
                            addScore(parts[0], parts[3], Double.parseDouble(parts[5]));
                        }
                        break;
                }
            }

            System.out.println("数据加载成功（含学生、课程、成绩）");
        } catch (IOException | NumberFormatException e) {
            System.out.println("加载失败：" + e.getMessage());
        }
    }

    // 辅助方法：计算GPA（仅用于存储，不输出控制台）
    private double calculateGPAForSave(String studentId) {
        double totalPoints = 0.0;
        int totalCredits = 0;
        for (Score score : scores) {
            if (score.getStudent().getStudentId().equals(studentId) && score.getScore() >= 60) {
                totalPoints += (score.getScore() / 20) * score.getCourse().getCredit();
                totalCredits += score.getCourse().getCredit();
            }
        }
        return totalCredits == 0 ? 0.0 : Math.round((totalPoints / totalCredits) * 100) / 100.0;
    }

    // 辅助方法：获取学分统计（所有课程总学分、及格课程总学分）
    private int[] getCreditStats(String studentId) {
        int allCredits = 0;
        int passCredits = 0;
        for (Score score : scores) {
            if (score.getStudent().getStudentId().equals(studentId)) {
                int credit = score.getCourse().getCredit();
                allCredits += credit;
                if (score.getScore() >= 60) {
                    passCredits += credit;
                }
            }
        }
        return new int[]{allCredits, passCredits};
    }

    // 辅助方法：根据学号查找学生
    private Student findStudentById(String studentId) {
        for (Student s : students) {
            if (s.getStudentId().equals(studentId)) return s;
        }
        return null;
    }

    // 辅助方法：根据课程编号查找课程
    private Course findCourseById(String courseId) {
        for (Course c : courses) {
            if (c.getCourseId().equals(courseId)) return c;
        }
        return null;
    }

    // 辅助方法：校验重复成绩
    private boolean hasDuplicateScore(String studentId, String courseId) {
        for (Score s : scores) {
            if (s.getStudent().getStudentId().equals(studentId) && s.getCourse().getCourseId().equals(courseId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 主方法：测试系统功能
     */
    public static void main(String[] args) {
        ScoreManagementSystem system = new ScoreManagementSystem();
        system.loadData();

        // 添加测试数据
        system.addCourse(new Course("C001", "Java编程", 4));
        system.addCourse(new Course("C002", "数据结构", 3));
        system.addStudent(new Student("2023001", "张三", "计算机一班"));
        system.addStudent(new Student("2023002", "李四", "计算机二班"));

        // 添加成绩
        system.addScore("2023001", "C001", 85);   // 及格，4学分
        system.addScore("2023001", "C002", 55);   // 不及格，3学分
        system.addScore("2023002", "C001", 78);   // 及格，4学分
        system.addScore("2023002", "C002", 90);   // 及格，3学分

        // 查询课程成绩
        system.queryScoresByCourse("Java编程");
        system.queryScoresByCourse("数据结构");

        // 计算GPA
        System.out.println("\n===== GPA计算详情 =====");
        system.calculateGPA("2023001");
        system.calculateGPA("2023002");

        // 保存数据（含GPA）
        system.saveData();
    }
}